﻿//-----------------------------------------------------------------------
// <copyright file="Type.cs">
//     Copyright (c) Nicole Calinoiu. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Xml;

using Microsoft.FxCop.Sdk;

namespace Bordecal.FxCop.Sdk.Testing
{
	/// <summary>
	/// Represents a .NET type screened by FxCop.
	/// </summary>
	internal sealed class Type : Target
	{
		internal Type(Namespace parent, XmlElement element)
			: base(parent, element)
		{
			this.NodeType = Type.ParseKind(element.GetAttribute("Kind"));
			this.IsExternallyVisible = bool.Parse(element.GetAttribute("ExternallyVisible"));
		}

		public Type(TypeNode type)
			: base(new Namespace(new Module(type.DeclaringModule), Type.GetNamespaceName(type)), type.Name.Name)
		{
			this.NodeType = type.NodeType;
			this.IsExternallyVisible = type.IsVisibleOutsideAssembly;

			if (type.DeclaringType != null)
			{
				this.Name = type.DeclaringType.Name.Name + "+" + this.Name;
			}
		}

		/// <summary>
		/// Gets the <see cref="NodeType"/> of the type.
		/// </summary>
		internal NodeType NodeType { get; private set; }

		/// <summary>
		/// Gets a value indicating whether the type may be accessed from outside its assembly.
		/// </summary>
		internal bool IsExternallyVisible { get; private set; }

		private static NodeType ParseKind(string kind)
		{
			NodeType result;
			switch (kind)
			{
				case "Class":
					result = NodeType.Class;
					break;
				case "Delegate":
					result = NodeType.DelegateNode;
					break;
				case "Enum":
					result = NodeType.EnumNode;
					break;
				case "Interface":
					result = NodeType.Interface;
					break;
				case "Struct":
					result = NodeType.Struct;
					break;
				default:
					result = NodeType.Undefined;
					break;
			}

			return result;
		}

		private static string GetNamespaceName(TypeNode type)
		{
			string result;
			if (type.DeclaringType != null)
			{
				result = Type.GetNamespaceName(type.DeclaringType);
			}
			else
			{
				result = type.Namespace.Name;
			}

			return result;
		}

		internal override bool Equals(Target target)
		{
			bool result = false;
			if (base.Equals(target))
			{
				Type type = (Type)target;
				if ((type.NodeType == this.NodeType) &&
					(type.IsExternallyVisible == this.IsExternallyVisible))
				{
					result = true;
				}
			}

			return result;
		}
	}
}